Essential Batch

Must Watch!



MustWatch



Introduction

This book describes Windows scripting as implemented by cmd.exe command interpreter. This book first describes using the Windows NT command interpreter, how it receives, parses, and processes commands from users. Then it describes various commands available. To obtain an extensive list of Windows commands and their short summaries, open the command prompt on any Windows computer, and type help. To find out about a particular command, type the name of the command followed by /?. The subject of this book is also known as "batch programming", even though "batch" refers not only to batch files for MS DOS and Windows command interpreter. Other subject terms include "batch file programming", "batch file scripting", "Windows batch command", "Windows batch file", "Windows command line", "Windows command prompt", and "Windows shell scripting".

How a command line is interpreted

The parsing of a command line into a sequence of commands is complex, and varies subtly from command interpreter to command interpreter. There are, however, four main components: Variable substitution A command line is scanned for variable specifications, and any found are replaced with the contents of those variables. Quoting `Special characters can be quoted, to remove their special meanings. Syntax Command lines are developed into a sequence of commands according to a syntax. Redirection Redirection specifications are applied, and removed from the command line, before an individual command in a sequence is executed.

Variable substitution

Command lines can contain variable specifications. These comprise a % character followed by a name, followed by a second % character unless the name is a digit in 0 ... 9 or an asterisk *. Variable specifications are replaced with values as follows: %%, such as %PATH% or %USERNAME%, is replaced with the value of the named environment variable. For example, %PATH% is replaced by the value of the PATH environment variable.varname % for 0 <= n <= 9, such as %0 or %9, is replaced with the value of the n-th parameter passed to the batch file when it was invoked, subject to any subsequent modifications by the SHIFT command. For example: %2 is replaced by the value of the second batch file parameter.n %* is replaced with the values of all the command-line parameters except for %0, even those beyond index 9. SHIFT command has no impact on the result of %*. See also command-line arguments.

Special names

Some variable names are not visible using SET command. Rather, they are made available for reading using the % notation. To find out about them, type help set. Special variable names and what they expand to:

Name Replacement Value Used
%CD% The current directory, not ending in a slash character if it is not the root directory of the current drive
%TIME% The system time in HH:MM:SS.mm format.
%DATE% The system date in a format specific to localization.
%RANDOM% A generated pseudo-random number between 0 and 32767.
%ERRORLEVEL% The error level returned by the last executed command, or by the last called batch script.
%CMDEXTVERSION% The version number of the Command Processor Extensions currently used by cmd.exe.
%CMDCMDLINE% The content of the command line used when the current cmd.exe was started.

Quoting and escaping

You can prevent the special characters that control command syntax from having their special meanings as follows, except for the percent sign (%): You can surround a string containing a special character by quotation marks. You can place caret (^), an escape character, immediately before the special characters. In a command located after a pipe (|), you need to use three carets (^^^) for this to work. The special characters that need quoting or escaping are usually <, >, |, &, and ^. In some circumstances, ! and \ may need to be escaped. A newline can be escaped using caret as well. When you surround the string using quotation marks, they become part of the argument passed to the command invoked. By contrast, when you use caret as an escape character, the caret does not become part of the argument passed. The percent sign (%) is a special case. On the command line, it does not need quoting or escaping unless two of them are used to indicate a variable, such as %OS%. But in a batch file, you have to use a double percent sign (%%) to yield a single percent sign (%). Enclosing the percent sign in quotation marks or preceding it with caret does not work. Examples echo "Johnson & son"Echoes the complete string rather than splitting the command line at the & character. Quotes are echoed as well echo Johnson ^& sonAs above, but using caret before the special character ampersand. No quotes are echoed. echo Johnson & sonDoes not use an escape character and therefore, "son" is interpreted as a separate command, usually leading to an error message that command son is not found. echo A ^^ BEchoes A ^ B. Caret needs escaping as well or else it is interpreted as escaping a space. echo > NUL | echo A ^^^^ BEchoes A ^ B. When after a pipe, a caret used for escaping needs to be tripled to work; the fourth caret is the one being escaped. if 1 equ 1 ^echo Equal &^echo Indeed, equalEchoes the two strings. The caret at the end of the line escapes the newlines, leading to the three lines being treated as if they were a single line. The space before the first caret is necessary or else 1 gets joined with the following echo to yield 1echo. attrib File^ 1.txtDoes not show attributes of file named File 1.txt since escaping of space does not work. Using quotes, as in attrib "File 1.txt", works. echo The ratio was 47%.If run from a batch, the percent sign is ignored. echo The ratio was 47%%.If run from a batch, the percent sign is output once. set /a modulo=14%%3If run from a batch, sets modulo variable to 2, the remainder of dividing 14 by 3. Does not work with single %. for %%i in (1,2,3) do echo %%iIf run from a batch, outputs 1, 2 and 3. echo %temp%Outputs the content of temp variable even if run from a batch file. Use of the percent sign in a batch to access environment variables and passed arguments needs no escaping. echo ^%temp^%Outputs literally %temp% when run from the command line. echo %%temp%%Outputs literally %temp% when run from a batch. echo //comment line | findstr \//Command FINDSTR uses backslash (\) for escaping. Unlike caret, this is internal to the command and unknown to the command shell.

Syntax

Command lines are developed into a sequence of commands according to a syntax. In that syntax, simple commandsmay be combined to form pipelines, which may in turn be combined to form compound commands, which finally may be turned into parenthesized commands. A simple command is just a command name, a command tail, and some redirection specifications. An example of a simple command is dir *.txt > somefile. A pipeline is several simple commands joined together with the "pipe" metacharacter ¡ª |, also known as the "vertical bar". The standard output of the simple command preceding each vertical bar is connected to the standard input of the simple command following it, via a pipe. The command interpreter runs all of the simple commands in the pipeline in parallel. An example of a pipeline (comprising two simple commands) is dir *.txt | more. A compound command is a set of pipelines separated by conjunctions. The pipelines are executed sequentially, one after the other, and the conjunction controls whether the command interpreter executes the next pipeline or not. An example of a compound command (comprising two pipelines, which themselves are just simple commands) is move file.txt file.bak && dir > file.txt. The conjunctions: & - An unconditional conjunction. The next pipeline is always executed after the current one has completed executing. && - A positive conditional conjunction. The next pipeline is executed if the current one completes executing with a zero exit status. || - A negative conditional conjunction. The next pipeline is executed if the current one completes executing with a non-zero exit status. A parenthesized command is a compound command enclosed in parentheses (i.e. ( and )). From the point of view of syntax, this turns a compound command into a simple command, whose overall output can be redirected. For example: The command line ( pushd temp & dir & popd ) > somefile.txt causes the standard output of the entire compound command ( pushd temp & dir & popd ) to be redirected to somefile.txt.

Redirection

Redirection specifications are applied, and removed from the command line, before an individual command in a sequence is executed. Redirection specifications control where the standard input, standard output, and standard error file handles for a simple command point. They override any effects to those file handles that may have resulted from pipelining. (See the preceding section on command syntax.) Redirection signs > and >> can be prefixed with 1 for the standard output (same as no prefix) or 2 for the standard error. The redirection specifications are: < filename Redirect standard input to read from the named file. > filename Redirect standard output to write to the named file, overwriting its previous contents. >> filename Redirect standard output to write to the named file, appending to the end of its previous contents. >&h Redirect to handle h, where handle is any of 0¡ªstandard input, 1¡ªstandard output, 2¡ªstandard error, and more. <&h Redirect from handle h. Examples: dir *.txt >listing.logRedirects the output of the dir command to listing.log file. dir *.txt > listing.logAs above; the space before the file name makes no difference. However, if you type this into the command window, auto-completion with tab after typing > l actually works, while it does not work with >listing.log. dir *.txt 2>NULRedirects errors of the dir command to nowhere. dir *.txt >>listing.logRedirects the output of the dir command to listing.log file, appending to the file. Thereby, the content of the file before the redirected command was executed does not get lost. dir *.txt >listing.log 2>&1Redirects the output of the dir command to listing.log file, along with the error messages. dir *.txt >listing.log 2>listing-errors.logRedirects the output of the dir command to listing.log file, and the error messages to listing-errors.log file. >myfile.txt echo HelloThe redirection can precede the command. echo Hello & echo World >myfile.txtOnly the 2nd echo gets redirected. (echo Hello & echo World) >myfile.txtOutput of both echos gets redirected. type con >myfile.txtRedirects console input (con) to the file. Thus, allows multi-line user input terminated by user pressing Control + Z. See also user input. (for %i in (1,2,3) do @echo %i) > myfile.txtRedirects the entire output of the loop to the file. for %i in (1,2,3) do @echo %i > myfile.txtStarts redirection anew each time the body of the loop is entered, losing the output of all but the latest loop iteration.

Batch reloading

The command interpreter reloads the content of a batch after each execution of a line or a bracketed group. If you start the following batch and change echo A to echo B in the batch shortly after starting it, the output will be B. @echo off ping -n 6 127.0.0.1 >nul & REM wait echo A What is on a single line does matter; changing echo A in the following batch after running it has no impact: @echo off ping -n 6 127.0.0.1 >nul & echo A Nor have after-start changes have any impact on commands bracketed with ( and ). Thus, changing echo A after starting the following batch has no impact: @echo off for /L %%i in (1,1,10) do ( ping -n 2 127.0.0.1 >nul & REM wait echo A ) Same happens for any other enclosing, including: @echo off ( ping -n 6 127.0.0.1 >nul & REM wait echo A )

Environment variables

The environment variables of the command interpreter process are inherited by the processes of any (external) commands that it executes. A few environment variables are used by the command interpreter itself. Changing them changes its operation. Environment variables are affected by the SET, PATH, and PROMPT commands. To unset a variable, set it to empty string, such as set myvar=. The command interpreter inherits its initial set of environment variables from the process that created it. In the case of command interpreters invoked from desktop shortcuts this will be Windows Explorer, for example. Command interpreters generally have textual user interfaces, not graphical ones, and so do not recognize the Windows message that informs applications that the environment variable template in the Registry has been changed. Changing the environment variables in Control Panel will cause Windows Explorer to update its own environment variables from the template in the Registry, and thus change the environment variables that any subsequently invoked command interpreters will inherit. However, it will not cause command interpreters that are already running to update their environment variables from the template in the Registry.

COMSPEC

The COMSPEC environment variable contains the full path name of the command interpreter program file. This is just inherited from the parent process, and is thus indirectly derived from the setting of COMSPEC in the environment variable template in the Registry.

PATH

The value of the PATH environment variable comprises a list of directory names, separated by semi-colon characters. This is the list of directories that are searched, in order, when locating the program file of an external command to execute.

PATHEXT

The value of the PATHEXT environment variable comprises a list of filename extensions, separated by semi-colon characters. This is the list of filename extensions that are applied, in order, when locating the program file of an external command to execute. An example content of PATHEXT printed by echo %PATHEXT%: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC By adding ".PL" to the variable, you can ensure Perl programs get run from the command line even when typed without the ".pl" extension. Thus, instead of typing "mydiff.pl a.txt b.txt", you can type "mydiff a.txt b.txt". Adding ".PL" to the variable in Windows Vista and later: setx PATHEXT %PATHEXT%;.PLIf you use "set" available in Windows XP, the effect will be temporary and impacting only the current console or process. Links:

PROMPT

The PROMPT environment variable controls the text emitted when the command interpreter displays the prompt. The command interpreter displays the prompt when prompting for a new command line in interactive mode, or when echoing a batch file line in batch file mode. Various special character sequences in the value of the PROMPT environment variable cause various special effects when the prompt is displayed, as in the following table:

Characters Expansion Result
$$ $ character itself
$A & symbol AKA ampersand. A convenience, since it is difficult to place a literal & in the value of the PROMPT environment variable using the SET command.
$B Vertical bar '|' (pipe symbol)
$C Left parenthesis '('
$D Current date
$E ESC (ASCII code 27)
$F Right parenthesis ')'
$G Greater-than symbol '>'
$H Backspace (deletes previous character)
$L Less-than symbol '<'
$M Remote name linked to the current drive if it is a network drive; empty string otherwise.
$N Current drive letter
$P Current drive letter and full path
$Q '=' (equals sign)
$S ' ' (space character)
$T Current system time
$V Windows version number
$_ <CR> (carriage return character, aka "enter")
$+ As many plus signs (+) as there are items on the pushd directory stack

Switches

Most Windows commands provide switches AKA options to direct their behavior. Observations: Switches most often consist of a single-letter; some switches consist of a sequence of multiple letters. Switches are preceded with a slash (/) rather than, as in some other operating systems, with a minus sign (-). Switches are case-insensitive rather than, as in some other operating systems, case-sensitive. If a command from another operating system is ported to Windows (such as grep), it usually retains the option conventions from the original operating system, including the use of minus sign and case-sensitivity. Examples: dir /?Displays the help. This option is provided by many commands. dir /b /sLists all files and folders in the current folder recursively. Two switches are used: /b and /s. dir /bsDoes not work; switches cannot be accumulated behind a single slash. findstr /ric:"id: *[0-9]*" File.txtUnlike many other commands, findstr allows the accumulation of switches behind a single slash. Indeed, r, i and c are single-letter switches. dir/b/sWorks. In dir, removing whitespace between the command and the first switch or between the switches does not make a difference; thus, does the same as dir /b /s. tree/f/aDoes not work, unlike tree /f /a. In tree, separation by whitespace is mandatory. Nor does find/i/v work. dir /odThe switch letter o is further modified by a single letter specifying that ordering should be by date. The letter d is not a switch by itself. Similar cases include dir /ad and more /t4. dir /B /SThe switches are case-insensitive, unlike in some other operating systems. sort /r file.txtSorts the file in a reverse order. sort /reverse file.txtSort allows the switch string to be longer than a single-letter. sort /reve file.txtSort allows the specified switch string to be a sub-string of the complete long name of the switch. Thus, does the same as the above. sort /reva file.txtDoes not work, since reva is not a sub-string of reverse. taskkill /im AcroRd32.exeTaskkill requires a multi-letter switch name for /im; shortening to /i does not work. java -versionJava, which originated in the environment of another operating system family, uses the minus convention for its switches AKA options. grep --helpIf GNU grep is installed, it requires multi-letter switches to be preceded by two dashes.

Error level

Commands usually set error level at the end of their execution. In Windows NT and later, it is a 32-bit signed integer; in MS DOS, it used to be an integer from 0 to 255. Keywords: return code, exit code, exit status. The conventional meaning of the error level: 0 - success not 0 - failure The error levels being set are usually positive. If the command does not distinguish various kinds of failure, the error level on failure is usually 1. Uses of the error level: It can be tested using && and ||; see also syntax. It can be tested using IF. The value can be accessed from ERRORLEVEL variable. Examples: dir >NUL && echo SuccessThe part after && is executed only if the error level is zero. color 00 || echo FailureThe part after || is executed only if the error level is non-zero, whether positive or negative. color 00 || ( echo Failure)Multi-line bracketing works as well. echo %ERRORLEVEL%Displays the error level without changing it. if %errorlevel% equ 0 echo The error level is zero, meaning success. if %errorlevel% neq 0 echo The error level is non-zero, meaning failure. if errorlevel 1 echo The error level is >= 1, meaning failure via positive error level.Does not cover failure via negative error level. Note the >= part: this is not the same as if %errorlevel% equ 1. exit /b 1Returns a batch file, setting the error level to 1. cmd /c "exit /b 10"In the middle of a batch file or on the command line, sets the error level to 10. (cmd /c "exit /b 0" && Echo Success) & (cmd /c "exit /b -1" || Echo Failure)As above, showing the error level is indeed affected. (cmd /c "exit /b 0" & cmd /c "exit /b 1") || Echo FailureThe error level of a chain created by & is the error level of the last command of the chain. cmd /c "exit /b -1" & if not errorlevel 1 echo Would-be successThe if not errorlevel 1 test, which might appear to test for success, passes on negative numbers: it tests on "not error level >= 1", which is "error level <= 0". set myerrorlevel=%errorlevel%Remembers the error level for later. set errorlevel=0To be avoided: overshadows the built-in errorlevel variable. Ensures that subsequent accesses via %ERRORLEVEL% return 0 rather than the actual error level. cmd /c "exit /b 0"if 1 equ 1 ( cmd /c "exit /b 1" & echo %errorlevel% )Displays 0, since %errorlevel% gets expanded before cmd /c "exit /b 1" gets executed.

String processing

Getting a substring of a variable: set a=abcdefgh echo %a:~0,1% & rem from index 0, length 1; result: a echo %a:~1,1% & rem from index 1, length 1; result: b echo %a:~0,2% & rem from index 0, length 2; result: ab echo %a:~1,2% & rem from index 1, length 2; result: bc echo %a:~1% & rem from index 1 to the end; result: bcdefgh echo %a:~-1% & rem from index -1 (last char) to the end; result: h echo %a:~-2% & rem from index -2 (next-to-last) to the end; result: gh echo %a:~0,-2% & rem from index 0 to index -2, excl.; result: abcdef echo %a:~0,-1% & rem from index 0 to index -1, excl.; result: abcdefg echo %a:~1,-1% & rem from index 1 to index -1, excl.; result: bcdefg Testing substring containment: if not "%a:bc=%"=="%a%" echo yes If variable a contains "bc" as a substring, echo "yes". This test is a trick that uses string replacement, discussed below. This test does not work if the variable contains a quotation mark. Testing for "starts with": if %a:~0,1%==a echo yes & rem If variable a starts with "a", echo "yes". if %a:~0,2%==ab echo yes & rem If variable a starts with "ab", echo "yes". String replacement: set a=abcd & echo %a:c=% & rem replace c with nothing; result: abd set a=abcd & echo %a:c=e% & rem replace c with e; result: abed; set a=abcd & echo %a:*c=% & rem replace all up to c with nothing; result: d rem Above, the asterisk (*) only works at the beginning of the sought pattern. See also the help for SET command: set /?. Splitting a string by any of " ", ",", and ";": ["space", "comma" and "semicolon":] set myvar=a b,c;d for %%a in (%myvar%) do echo %%a Splitting a string by semicolon, assuming the string contains no quotation marks: @echo off set myvar=a b;c;d set strippedvar=%myvar% :repeat for /f "delims=;" %%a in ("%strippedvar%") do echo %%a set prestrippedvar=%strippedvar% set strippedvar=%strippedvar:*;=% if not "%prestrippedvar:;=%"=="%prestrippedvar%" goto :repeat Limitations: The above string processing does not work with parameter variables (%1, %2, ...).

Command-line arguments

The command-line arguments AKA command-line parameters passed to a batch script are accessible as %1, %2, ..., %9. There can be more than nine arguments; to access them, see how to loop over all of them below. The syntax %0 does not refer to a command-line argument but rather to the name of the batch file. Testing for whether the first command-line argument has been provided: if not -%1-==-- echo Argument one provided if -%1-==-- echo Argument one not provided & exit /b A robust looping over all command-line arguments using SHIFT (for each command-line argument, ...): :argactionstart if -%1-==-- goto argactionend echo %1 & REM Or do any other thing with the argument shift goto argactionstart :argactionend A robust looping over all command-line arguments using SHIFT without modifying %1, %2, etc.: call :argactionstart %* echo Arg one: %1 & REM %1, %2, etc. are unmodified in this location exit /b :argactionstart if -%1-==-- goto argactionend echo %1 & REM Or do any other thing with the argument shift goto argactionstart :argactionend exit /b Transferring command-line arguments to environment variables: setlocal EnableDelayedExpansion REM Prevent affecting possible callers of the batch REM Without delayed expansion, !arg%argno%! used below won't work. set argcount=0 :argactionstart if -%1-==-- goto argactionend set /a argcount+=1 set arg%argcount%=%1 shift goto argactionstart :argactionend set argno=0 :loopstart set /a argno+=1 if %argno% gtr %argcount% goto loopend echo !arg%argno%! & REM Or do any other thing with the argument goto loopstart :loopend Looping over all command-line arguments, albeit not a robust one: for %%i in (%*) do ( echo %%i ) This looks elegant but is non-robust, maltreating arguments containing wildcards (*, ?). In particular, the above for command replaces arguments that contain wildcards (*, ?) with file names that match them, or drops them if no files match. Nonetheless, the above loop works as expected as long as the passed arguments do not contain wildcards. Finding the number of command-line arguments, in a non-robust way: set argcount=0 for %%i in (%*) do set /a argcount+=1 Again, this does not work with arguments containing wildcards. The maximum possible number of arguments is greater than 4000, as empirically determined on a Windows Vista machine. The number can differ on Windows XP and Windows 7. In passing arguments to a batch script, characters used for argument separation are the following ones: space comma semicolon equal sign tab character Thus, the following lines pass the same four arguments: test.bat a b c d test.bat a,b,c,d test.bat a, b, c, d test.bat a;b;c;d test.bat a=b=c=d test.bat a b,c;,;=d Yes, even the line with a b,c;,;=d passes four arguments, since a sequence of separating characters is considered a single separator. To have a space, comma or semicolon in the argument value, you can pass the value enclosed in quotation marks. However, the quotation marks become part of the argument value. To get rid of the enclosing quotation marks when referring to the argument in the script, you can use %~<number> described in percent tilde. When passing arguments to an invoked command rather than a batch script, you usually need to separate the command from the first argument using a space. However, for internal commands, that separation is not necessary if the first character after the command name is one of a couple of symbols, including .\/, and more: echo.Outputs a newline. tree.Fails: "tree." not found. tree is an external command. dir..Lists the content of the parent directory. cd..Changes the current directory to the parent one. cd\Changes the current directory to the root one. start.Opens Windows Explorer from the current directory. dir/b/sLists directory content recursively, showing full paths.

Wildcards

Many commands accept file name wildcards--characters that do not stand for themselves and enable matching of a group of filenames. Wildcards: * : any sequence of characters ? : a single character other than a period (.) or, if part of a sequence of question marks at the end of a maximum period-free part of a file name, possibly zero number of characters; see examples for clarification Examples: dir *.txtMatches Myfile.txt, Plan.txt and any other file with the .txt extension. dir *txtThe period does not need to be included. However, this will also match files named without the period convention, such as myfiletxt. ren *.cxx *.cppRenames all files with .cxx extension to have .cpp extension. dir a?b.txt Matches files aab.txt, abb.txt, a0b.txt, etc. Does not match ab.txt, since a question mark followed by a character other than a question mark or period cannot match zero characters. Does not match a.b.txt, since a question mark cannot match a period. dir ???.txtMatches .txt, a.txt, aa.txt, and aaa.txt, among others, since each question mark in the sequence followed by a period can match zero number of characters. dir a???.b???.txt???Matches a.b.txt, among others. While the last question mark sequence is not followed by a period, it is still a sequence at the end of a maximum period-free part of a file name. dir ????????.txt & @REM eight question marksMatches the same files as *.txt, since each file also has a short file name that has no more than 8 characters before .txt. Quirk with short file names: the wildcard matching is performed both on long file names and the usually hidden short 8 chars + period + 3 chars file names. This can lead to bad surprises. Unlike shells of some other operating systems, the cmd.exe shell does not perform wildcard expansion (replacement of the pattern containing wildcards with the list of file names matching the pattern) on its own. It is the responsibility of each program to treat wildcards as such. This enables such things as ren *.txt *.bat, since the ren command actually sees the * wildcard rather than a list of files matching the wildcard. Thus, echo *.txt does not display files in the current folder matching the pattern but rather literally displays *.txt. Another consequence is that you can write findstr a.*txt without fearing that the a.*txt part gets replaced with the names of some files in the current folder. Furthermore, recursive findstr /s pattern *.txt is possible, while in some other operating systems, the *.txt part would get replaced with the file names found in the current folder, disregarding nested folders. Commands accepting wildcards include ATTRIB, COPY, DIR, FINDSTR, FOR, REN, etc.

User input

You can get input from the user using the following methods: SET /P command CHOICE command Using type con >myfile.txt, for which the multi-line user input is terminated by user pressing Control + Z.

%~ (percent tilde)

When a command-line argument contains a file name, special syntax can be used to get various information about the file. The following expand to various information about the file passed as %1:

Syntax Expansion Result Example
%~1 %1 with no enclosing quotation marks Not provided
%~f1 Full path with a drive letter C:\Windows\System32\notepad.exe
%~d1 Drive letter C:
%~p1 Drive-less path with the trailing backslash \Windows\System32\
%~n1 For a file, the file name without path and extensionFor a folder, the folder name notepad
%~x1 File name extension including the period .exe
%~s1 Modify of f, n and x to use short name Not provided
%~a1 File attributes --a------
%~t1 Date and time of last modification of the file 02.11.2006 11:45
%~z1 File size 151040
%~pn1 A combination of p and n \Windows\System32\notepad
%~dpnx1 A combination of several letters C:\Windows\System32\notepad.exe
%~$PATH:1 The full path of the first match found in the folders present in the PATH variable, or an empty string in no match.
%~n0 %~n applied to %0:The extensionless name of the batch tildetest
%~nx0 %~nx applied to %0:The name of the batch tildetest.bat
%~d0 %~f applied to %0:The drive letter of the batch C:
%~dp0 %~dp applied to %0:The folder of the batch with trailing backslash C:\Users\Joe Hoe\
The same syntax applies to single-letter variables created by FOR command, such as %%i.

Functions

Functions AKA subprograms can be emulated using CALL, labels, SETLOCAL and ENDLOCAL. An example of a function that determines arithmetic power: @echo off call :power 2 4 echo %result% rem Prints 16, determined as 2 * 2 * 2 * 2 goto :eof rem __Function power______________________ rem Arguments: %1 and %2 :power setlocal set counter=%2 set interim_product=%1 :power_loop if %counter% gtr 1 ( set /a interim_product=interim_product * %1 set /a counter=counter - 1 goto :power_loop ) endlocal & set result=%interim_product% goto :eof While the goto :eof at the end of the function is not really needed, it has to be there in the general case in which there is more than one function. The variable into which the result should be stored can be specified on the calling line as follows: @echo off call :sayhello result=world echo %result% exit /b :sayhello set %1=Hello %2 REM Set %1 to set the returning value exit /b In the example above, exit /b is used instead of goto :eof to the same effect. Also, remember that the equal sign is a way to separate parameters. Thus, the following items achieve the same: call :sayhello result=world call :sayhello result world call :sayhello result,world call :sayhello result;world (See command-line arguments as a reminder)

Calculation

Batch scripts can do simple 32-bit integer arithmetic and bitwise manipulation using SET /a command. The largest supported integer is 2147483647 = 2 ^ 31 - 1. The smallest supported integer is -2147483648 = - (2 ^ 31), assignable with the trick of set /a num=-2147483647-1. The syntax is reminiscent of the C language. Arithmetic operators include *, /, % (modulo), +, -. In a batch, modulo has to be entered as "%%". Bitwise operators interpret the number as a sequence of 32 binary digits. These are ~ (complement), & (and), | (or), ^ (xor), << (left shift), >> (right shift). A logical operator of negation is !: it turns zero into one and non-zero into zero. A combination operator is ,: it allows more calculations in one set command. Combined assignment operators are modeled on "+=", which, in "a+=b", means "a=a+b". Thus, "a-=b" means "a=a-b". Similarly for *=, /=, %=, &=, ^=, |=, <<=, and >>=. The precedence order of supported operators, is as follows:
    ( ) * / % + - << >> & ^ | = *= /= %= += -= &= ^= |= <<= >>= ,
Literals can be entered as decimal (1234), hexadecimal (0xffff, leading 0x), and octal (0777, leading 0). The internal bit representation of negative numbers is two's complement. This provides a connection between arithmetic operations and bit operations. For instance, -2147483648 is represented as 0x80000000, and therefore set /a num=~(-2147483647-1) yields 2147483647, which equals 0x7FFFFFFF (type set /a num=0x7FFFFFFF to check). As some of the operators have special meaning for the command interpreter, an expression using them needs to be enclosed in quotation marks, such as this: set /a num="255^127" set /a "num=255^127"Alternative placement of quotation marks. set /a num=255^^127Escape ^ using ^ instead of quotation marks. Examples: set n1=40 & set n2=25set /a n3=%n1%+%n2% Uses the standard percent notation for variable expansion. set n1=40 & set n2=25set /a n3=n1+n2 Avoids the percent notation around variable names as unneeded for /a. set /a num="255^127"Encloses "^" in quotation marks to prevent its special meaning for the command interpreter. set /a n1 = (10 + 5)/5The spaces around = do not matter with /a. However, getting used to it lends itself to writing "set var = value" without /a, which sets the value of "var " rather than "var". if 1==1 (set /a n1=(2+4)*5)Does not work: the arithmetic brackets within grouping brackets cause trouble. if 1==1 (set /a n1=^(2+4^)*5)Escaping the arithmetic brackets with caret (^) works, as does enclosing "n1=2+(4*5)" in quotation marks. set /a n1=2+3,n2=4*7Performs two calculations. set /a n1=n2=2Has the same effect as n1=2,n2=2. set n1=40 & set n2=25 & set /a n3=n1+n2Works as expected. set /a n1=2,n2=3,n3=n1+n2Works as expected. set n1=40 & set n2=25 & set /a n3=%n1%+%n2%Does not work unless n1 and n2 were set previously. The variable specifications %n1%" and "%n2"% get expanded the first set command is executed. Dropping percent notation makes it work.before set /a n1=2,n2=3,n3=%n1%+%n2%Does not work unless n1 and n2 were set previously, for the reason stated in the previous example. set /a n1=0xffffSets n1 using hexadecimal notation. set /a n1=0777Sets n1 using octal notation. set /a n1=%random%A pseudo-random number from 0 to 32767 = 2^15-1. set /a n1="%random%>>10"A pseudo-random number from 0 to 31 = 2^5-1. The shift right operator drops 10 out of 15 bits, keeping 5 bits. set /a n1=%random%%50A pseudo-random number from 0 to 49. Uses the % modulo operator. In a batch, %% is needed for modulo: set /a n1=%random%%%50. Because of this particular use of the modulo, the result is not perfectly uniform; it is uniform if the 2nd modulo operand--above 50--equals to a power of 2, e.g. 256 = 2^8. set /a n1="(%random%<<15)+%random%"A pseudo-random number from 0 to 1073741823 = 2^30 - 1. Combines the two 15-bit random numbers produced by %random% alone to produce a single 30-bit random number.. set /a n1="((%random%<<15)+%random%)%1000000"As above, but again using modulo, this time to achieve the range 0 to 999999. An example calculation that prints prime numbers: @echo off setlocal set n=1 :print_primes_loop set /a n=n+1 set cand_divisor=1 :print_primes_loop2 set /a cand_divisor=cand_divisor+1 set /a cand_divisor_squared=cand_divisor*cand_divisor if %cand_divisor_squared% gtr %n% echo Prime %n% & goto :print_primes_loop set /a modulo=n%%cand_divisor if %modulo% equ 0 goto :print_primes_loop & REM Not a prime goto :print_primes_loop2

Finding files

Files can be found using DIR, FOR, FINDSTR, FORFILES, and WHERE. Examples: dir /b /s *base*.doc*Outputs all files in the current folder and its sub-folders such that the file name before the extension contains the word base and whose extension starts with doc, which includes doc and docx. The files are output with full paths, one file per line. dir /b /s *.txt | findstr /i pers.*docCombines the result of outputting files including their complete paths with the findstr filtering command supporting limited regular expressions, yielding a versatile and powerful combination for finding files by names and the names of their directories. for /r %i in (*) do @if %~zi geq 1000000 echo %~zi %iFor each file in the current folder and its sub-folders that has the size greater than or equal to 1,000,000 bytes, outputs the file size in bytes and the full path of the file. For the syntax in %~zi, see percent tilde. forfiles /s /d 06/10/2015 /c "cmd /c echo @fdate @path"For each file in the current folder and its sub-folders modified on 10 June 2015 or later, outputs the file modification date and full file path. The date format after /d is locale specific. Thus, allows to find most recently modified files. (for /r %i in (*) do @echo %~ti :: %i) | findstr 2015.*::Searching the current folder recursively, outputs files whose last modification date is in year 2015. Places the modification date and time, followed by a double colon, before the file name. Works as long as the used version of Windows and locale displays dates in a format that contains four-digit years. The double colon is used to make sure the findstr command is matching the date and not the file name. for /r %i in (*) do @echo %~ti | findstr 2015 >NUL && echo %iAs above, outputs files changed in 2015. Unlike the above, only outputs the files, not the modification dates. findstr /i /s /m cat.*mat *.txtFinds files by their content. Performs a full text search for regular expression cat.*mat in files with names ending in .txt, and outputs the files names. The /m switch ensures only the file names are output. where *.batOutputs all .bat files in the current directory and in the directories that are in PATH.

Keyboard shortcuts

When using Windows command line from the standard console that appears after typing cmd.exe after pressing Windows + R, you can use multiple keyboard shortcuts, including function keys: Tab: Completes the relevant part of the typed string from file names or folder names in the current folder. The relevant part is usually the last space-free part, but use of quotation marks changes that. Generally considers both files and folders for completion, but cd command only considers folders. Up and down arrow keys: Enters commands from the command history, one at a time. Escape: Erases the current command line being typed. F1: Types the characters from the single previously entered command from the command history, one character at a time. Each subsequent press of F1 enters one more character. F2: Asks you to type a character, and enters the shortest prefix of the previous command from the command history that does not include the typed character. Thus, if the previous command was echo Hello world and you typed o, enters ech. F3: Enters the single previous command from the command history. Repeated pressing has no further effect. F4: Asks you to type a character, and erases the part of the currently typed string that starts at the current cursor location, continues to the right, and ends with the character you entered excluding that character. Thus, if you type echo Hello world, place the cursor at H using left arrow key, press F4 and then w, you get echo world. F5: Enters previous commands from the command history, one at a time. F6: Enters Control+Z character. F7: Opens a character-based popup window with the command history, and lets you use arrow key and enter to select a command. After you press enter in the popup, the command is immediately executed. F8: Given an already typed string, shows items from the command history that have that string as a prefix, one at a time. F9: Lets you enter the number of the command from the command history, and then executes the command. Alt + F7: Erases the command history. The above are also known as command prompt keyboard shortcuts. The availability of the above shortcuts does not seem to depend on running DOSKEY.

Paths

File and directory paths follow certain conventions. These include the possible use of a drive letter followed by a colon (:), the use of backslash (\) as the path separator, and the distinction between relative and absolute paths. Forward slash (/) often works when used instead of (\) but not always; it is normally used to mark switches (options). Using forward slash can lead to various obscure behaviors, and is best avoided. Special device names include NUL, CON, PRN, AUX, COM1, ..., COM9, LPT1, ..., LPT9; these can be redirected to. Examples: attrib C:\Windows\System32\notepad.exeSucceeds if the file exists, as it should. This is an absolute path with a drive letter. It is also known as a fully qualified path. attrib \Windows\System32\notepad.exeSucceeds if the current drive is C:, and if the file exists, as it should. This is an absolute path without a drive letter. cd /d C:\Windows & attrib System32\notepad.exeSucceeds if the file exists. The path given to attrib is a relative path. cd /d C:\Windows\System32 & attrib C:notepad.exeSucceeds if the file exists. The path given to attrib is a one despite containing a drive letter: there would have to be C:\notepad.exe with a backslash for that to be an absolute path.relative cd /d C:\Windows & attrib .\System32\notepad.exeSucceeds if the file exists. A single period denotes the current folder. attrib .A single period denotes the current folder. cd /d C:\Windows & attrib .\System32\\\notepad.exeSucceeds if the file exists. Piling of backslashes has no impact beyond the first backslash. cd /d C:\Windows & attrib .\System32Succeeds if the folder exists. cd /d C:\Windows & attrib .\System32\Fails. Folders are usually denoted without the final backslash. cd C:\Windows\System32\Succeeds. cd ..A double period denotes the parent folder. attrib C:\Windows\System32\..\..\Windows\System32A double period can be used in the middle of the path to navigate to the parent folder, even multiple times. attrib \\myserver\myvolumeA network UNC path starts with double backslash and no drive letter. cd \\myserver\myvolumeDoes not work; changing to a server folder in this direct manner does not work. pushd \\myserver\folderAutomatically creates a drive for the folder and changes to it. After you use POPD, the drive gets unassigned again. attrib C:/Windows/System32/notepad.exeSucceeds on multiple versions of cmd.exe. Uses forward slashes.

Arrays

Arrays can be emulated in the delayed expansion mode using the combination of % and ! to indicate variables. There, %i% is the value of variable i with the immediate expansion while !i! is the value of variable i in the delayed expansion. @echo off setlocal EnableDelayedExpansion for /l %%i in (1, 1, 10) do ( set array_%%i=!random! ) for /l %%i in (1, 1, 10) do ( echo !array_%%i! ) :: For each item in the array, not knowing the length set i=1 :startloop if not defined array_%i% goto endloop set array_%i%=!array_%i%!_dummy_suffix echo A%i%: !array_%i%! set /a i+=1 goto startloop :endloop

Perl one-liners

Some tasks can be conveniently achieved with Perl one-liners. Perl is a scripting language originating in the environment of another operating system. Since many Windows computing environments have Perl installed, Perl one-liners are a natural and compact extension of Windows batch scripting. Examples: echo "abcbbc"| perl -pe "s/a.*?c/ac/"Lets Perl act as sed, the utility that supports textual replacements specified using regular expressions. echo a b| perl -lane "print $F[1]"Lets Perl act as cut command, displaying the 2nd field or column of the line, in this case b. Use $F[2] to display 3rd field; indexing starts at zero. Native solution: FOR /f. perl -ne "print if /\x22hello\x22/" file.txtActs as grep or FINDSTR, outputting the lines in file.txt that match the regular expression after if. Uses the powerful Perl regular expressions, more powerful than those of FINDSTR. perl -ne "$. <= 10 and print" MyFile.txtLets Perl act as head -10 command, outputting the first 10 lines of the file. perl -e "sleep 5"Waits for 5 seconds. for /f %i in ('perl -MPOSIX -le "print strftime '%Y-%m-%d', localtime"') do @set isodate=%iGets current date in the ISO format into isodate variable. perl -MWin32::Clipboard -e "print Win32::Clipboard->Get()"Outputs the text content of the clipboard. When stored to getclip.bat, yields a handy getclip command to complement CLIP command. perl -MText::Diff -e "print diff 'File1.txt', 'File2.txt'"Outputs differences between two files in a format similar to diff command known from other operating systems, including context lines, lines starting with + and lines starting with -. On the web, Perl one-liners are often posted in the command-line conventions of another operating system, including the use of apostrophe (') to surround the arguments instead of Windows quotation marks. These need to be tweaked for Windows.

Limitations

There is no touch command familiar from other operating systems. The touch command would modify the last-modification timestamp of a file without changing its content. One workaround, with unclear reliability and applicability across various Windows versions, is this: copy /b file.txt+,,

Built-in commands

These commands are all built in to the command interpreter itself, and cannot be changed. Sometimes this is because they require access to internal command interpreter data structures, or modify properties of the command interpreter process itself.

Command Description
ASSOC Associates an extension with a file type (FTYPE).
BREAK Sets or clears extended CTRL+C checking.
CALL Calls one batch program from another.
CD, CHDIR Displays or sets the current directory.
CHCP Displays or sets the active code page number.
CLS Clears the screen.
COLOR Sets the console foreground and background colors.
COPY Copies files.
DATE Displays and sets the system date.
DEL, ERASE Deletes one or more files.
DIR Displays a list of files and subdirectories in a directory.
ECHO Displays messages, or turns command echoing on or off.
ELSE Performs conditional processing in batch programs when "IF" is not true.
ENDLOCAL Ends localization of environment changes in a batch file.
EXIT Quits the CMD.EXE program (command interpreter).
FOR Runs a specified command for each file in a set of files.
FTYPE Sets the file type command.
IF Performs conditional processing in batch programs.
MD, MKDIR Creates a directory.
MOVE Moves a file to a new location
PATH Sets or modifies the PATH environment
PAUSE Causes the command session to pause for user input.
POPD Changes to the drive and directory popped from the directory stack
PROMPT Sets or modifies the string displayed when waiting for input.
PUSHD Pushes the current directory onto the stack, and changes to the new directory.
RD / RMDIR Removes the directory.
REM A comment command. Unlike double-colon (::), the command can be executed.
REN / RENAME Renames a file or directory
SET Sets or displays shell environment variables
SETLOCAL Creates a child-environment for the batch file.
SHIFT Moves the batch parameters forward.
START Starts a program with various options.
TIME Displays or sets the system clock
TITLE Changes the window title
TYPE Prints the content of a file to the console.
VER Shows the command processor, operating system versions.
VERIFY Verifies that file copy has been done correctly.
VOL Shows the label of the current volume.

External commands

External commands available to Windows command interpreter are separate executable program files, supplied with the operating system by Microsoft, or bundled as standard with the third-party command interpreters. By replacing the program files, the meanings and functions of these commands can be changed. Many, but not all, external commands support the /? convention, causing them to write on-line usage information to their standard output and then to exit with a status code of 0.